package com.dd.cloud.auth.filter;

import com.dd.cloud.auth.config.LoginUser;
import com.dd.cloud.auth.contants.RoleConstants;
import com.dd.cloud.auth.security.TokenManager;
import com.dd.cloud.common.constants.HealthConstants;
import com.dd.cloud.common.constants.RedisKeyConstants;
import com.dd.cloud.common.enums.ZkExceptionEnum;
import com.dd.cloud.common.exception.ZekeException;
import com.dd.cloud.common.utils.JsonUtils;
import com.dd.cloud.common.vo.LoginInfo;
import com.dd.cloud.common.vo.LoginInfoTransfer;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 登录过滤器，继承UsernamePasswordAuthenticationFilter，对用户名密码进行登录校验
 * 系统已有登录流程, 用户到此即表示登录成功, 此处功能只为获取权限并设置到redis
 * </p>
 *
 * @author qy
 * @since 2019-11-08
 */
@Slf4j
public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {

    private AuthenticationManager authenticationManager;
    private TokenManager tokenManager;
    private RedisTemplate redisTemplate;

    public TokenLoginFilter(AuthenticationManager authenticationManager, TokenManager tokenManager, RedisTemplate redisTemplate) {
        this.authenticationManager = authenticationManager;
        this.tokenManager = tokenManager;
        this.redisTemplate = redisTemplate;
        this.setPostOnly(false);
        this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/power/roleId/by/userId","POST"));
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res)
            throws AuthenticationException {
        /**
         * 获取用户信息, 登录的user用json方式存放于body,取出
         */
        try {
            BufferedReader reader = req.getReader();
            StringBuilder builder = new StringBuilder();
            String line = reader.readLine();
            while(line != null){
                builder.append(line);
                line = reader.readLine();
            }
            reader.close();

            String loginInfo = builder.toString();

            return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(loginInfo, "", new ArrayList<>()));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

    /**
     * 登录成功, 设置reids, 并返回权限值
     * @param req
     * @param res
     * @param chain
     * @param auth
     * @throws IOException
     * @throws ServletException
     */
    @Override
    protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse res, FilterChain chain,
                                            Authentication auth) throws IOException, ServletException {
        LoginUser user = (LoginUser) auth.getPrincipal();
        List<String> permissions = user.getPermissions();
        //将能访问的uri存放于redis
        redisTemplate.opsForValue().set(RedisKeyConstants.CacheKey.AUTHROLEMENU + user.getLoginInfo().getRoleId(), permissions,240,TimeUnit.MINUTES);
        res.setStatus(HttpStatus.OK.value());
        res.setCharacterEncoding("UTF-8");
        res.setContentType("application/json;charset=utf-8");
        PrintWriter writer = null;
        try {
            writer = res.getWriter();
            //返回权限id给用户服务
            writer.print(JsonUtils.objectToStr(user.getAdminRole()));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (writer != null) {
                writer.close();
            }
        }
    }

    /**
     * 登录失败 系统暂时不会走到此流程
     * @param request
     * @param response
     * @param e
     * @throws IOException
     * @throws ServletException
     */
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
                                              AuthenticationException e) throws IOException, ServletException {
        log.debug("登录失败");
        throw new ZekeException("登录失败");
    }
}
